import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { RedisService } from '@/services/redis.service';
import { LoggingService } from '@/services/logging.service';
import { Sequence } from '@/entities/sequence.entity';
import { SequenceConfig, GeneratedSequence, SequenceStatistics } from '@/interfaces/sequence.interface';

@Injectable()
export class SequenceService {
    private readonly CACHE_PREFIX = 'seq:';
    private readonly CACHE_TTL = 3600; // 1小时缓存

    constructor(
        @InjectRepository(Sequence)
        private readonly sequenceRepository: Repository<Sequence>,
        private readonly redisService: RedisService,
        private readonly loggingService: LoggingService,
    ) {}

    /**
     * 生成下一个序列号
     */
    async generateNext(config: SequenceConfig): Promise<GeneratedSequence> {
        const { type, step = 1, digits = 6, description } = config;
        const datePrefix = this.getCurrentDatePrefix();

        try {
            // 尝试从Redis缓存获取
            const cachedValue = await this.getFromCache(type, datePrefix);
            if (cachedValue !== null) {
                const nextValue = cachedValue + step;
                await this.setCacheValue(type, datePrefix, nextValue);

                return {
                    sequenceNumber: this.formatSequenceNumber(datePrefix, nextValue, digits),
                    type,
                    datePrefix,
                    value: nextValue,
                };
            }

            // 从数据库获取或创建
            const sequence = await this.getOrCreateSequence(type, datePrefix, step, digits, description);
            const nextValue = sequence.currentValue + step;

            // 更新数据库
            sequence.currentValue = nextValue;
            await this.sequenceRepository.save(sequence);

            // 更新缓存
            await this.setCacheValue(type, datePrefix, nextValue);

            this.loggingService.app(`生成序列号: ${type} - ${datePrefix} - ${nextValue}`, {
                type,
                datePrefix,
                value: nextValue,
            });

            return {
                sequenceNumber: this.formatSequenceNumber(datePrefix, nextValue, digits),
                type,
                datePrefix,
                value: nextValue,
            };
        } catch (error) {
            this.loggingService.error(
                `生成序列号失败: ${error instanceof Error ? error.message : String(error)}`,
                error instanceof Error ? error : new Error(String(error)),
            );
            throw error;
        }
    }

    /**
     * 批量生成序列号
     */
    async generateBatch(config: SequenceConfig, count: number): Promise<GeneratedSequence[]> {
        const results: GeneratedSequence[] = [];

        for (let i = 0; i < count; i++) {
            const result = await this.generateNext(config);
            results.push(result);
        }

        return results;
    }

    /**
     * 重置序列号（按日期）
     */
    async resetSequence(type: string, datePrefix?: string): Promise<void> {
        const targetDate = datePrefix || this.getCurrentDatePrefix();

        try {
            // 清除缓存
            await this.clearCache(type, targetDate);

            // 重置数据库中的值
            await this.sequenceRepository.update({ type, datePrefix: targetDate }, { currentValue: 0 });

            this.loggingService.app(`重置序列号: ${type} - ${targetDate}`);
        } catch (error) {
            this.loggingService.error(
                `重置序列号失败: ${error instanceof Error ? error.message : String(error)}`,
                error instanceof Error ? error : new Error(String(error)),
            );
            throw error;
        }
    }

    /**
     * 获取序列号信息
     */
    async getSequenceInfo(type: string, datePrefix?: string): Promise<Sequence | null> {
        const targetDate = datePrefix || this.getCurrentDatePrefix();
        return await this.sequenceRepository.findOne({
            where: { type, datePrefix: targetDate },
        });
    }

    /**
     * 获取当前日期前缀
     */
    private getCurrentDatePrefix(): string {
        const now = new Date();
        const year = now.getFullYear();
        const month = String(now.getMonth() + 1).padStart(2, '0');
        const day = String(now.getDate()).padStart(2, '0');
        return `${year}${month}${day}`;
    }

    /**
     * 格式化序列号
     */
    private formatSequenceNumber(datePrefix: string, value: number, digits: number): string {
        const paddedValue = String(value).padStart(digits, '0');
        return `${datePrefix}${paddedValue}`;
    }

    /**
     * 从缓存获取值
     */
    private async getFromCache(type: string, datePrefix: string): Promise<number | null> {
        try {
            const key = this.getCacheKey(type, datePrefix);
            const value = await this.redisService.get(key);
            return value ? parseInt(value, 10) : null;
        } catch (error) {
            this.loggingService.error(`从缓存获取序列号失败: ${error instanceof Error ? error.message : String(error)}`);
            return null;
        }
    }

    /**
     * 设置缓存值
     */
    private async setCacheValue(type: string, datePrefix: string, value: number): Promise<void> {
        try {
            const key = this.getCacheKey(type, datePrefix);
            await this.redisService.set(key, value.toString(), this.CACHE_TTL);
        } catch (error) {
            this.loggingService.error(`设置缓存序列号失败: ${error instanceof Error ? error.message : String(error)}`);
        }
    }

    /**
     * 清除缓存
     */
    private async clearCache(type: string, datePrefix: string): Promise<void> {
        try {
            const key = this.getCacheKey(type, datePrefix);
            await this.redisService.del(key);
        } catch (error) {
            this.loggingService.error(`清除缓存序列号失败: ${error instanceof Error ? error.message : String(error)}`);
        }
    }

    /**
     * 获取缓存键
     */
    private getCacheKey(type: string, datePrefix: string): string {
        return `${this.CACHE_PREFIX}${type}:${datePrefix}`;
    }

    /**
     * 获取或创建序列号记录
     */
    private async getOrCreateSequence(type: string, datePrefix: string, step: number, digits: number, description?: string): Promise<Sequence> {
        let sequence = await this.sequenceRepository.findOne({
            where: { type, datePrefix },
        });

        if (!sequence) {
            sequence = this.sequenceRepository.create({
                type,
                datePrefix,
                currentValue: 0,
                step,
                digits,
                description,
                isActive: true,
            });

            await this.sequenceRepository.save(sequence);
            this.loggingService.app(`创建新序列号记录: ${type} - ${datePrefix}`);
        }

        return sequence;
    }

    /**
     * 获取序列号统计信息
     */
    async getStatistics(): Promise<SequenceStatistics> {
        const today = this.getCurrentDatePrefix();

        const [totalTypes, totalSequences, todayGenerated] = await Promise.all([
            this.sequenceRepository.createQueryBuilder('seq').select('COUNT(DISTINCT seq.type)', 'count').getRawOne(),

            this.sequenceRepository.count(),

            this.sequenceRepository.createQueryBuilder('seq').select('SUM(seq.currentValue)', 'sum').where('seq.datePrefix = :today', { today }).getRawOne(),
        ]);

        return {
            totalTypes: parseInt(totalTypes?.count || '0', 10),
            totalSequences: totalSequences,
            todayGenerated: parseInt(todayGenerated?.sum || '0', 10),
        };
    }
}
